// Sorting functions for comparing attributes in adobe::value_t
// Copyright 2005 (C) Ralph Thomas

#ifndef MODEL_SORT_H
#define MODEL_SORT_H

#include <boost/function.hpp>
#include <adobe/value.hpp>
#include <adobe/array.hpp>

namespace model {
	//
	/// This is the operator function for sorting adobe::value_ts. The function is
	/// always less-than.
	//
	typedef boost::function<bool (const adobe::value_t&,const adobe::value_t&)> sorter_t;
	//
	/// Return a function to sort the given attribute, if the given attribute has
	/// no meaningful comparison (for example, icons). The function is a less-than
	/// operator which exhibits partial-ordering.
	///
	/// \param	attr	the name of the attribute to return a sorter for.
	/// \return	a sorter function for the given attribute or an empty function
	///		if there is no sort for the given attribute.
	//
	sorter_t getSorter( const std::string& attr );
	//
	/// This class can manage a model's children and perform sorting on them. Obviously
	/// this is only useful to models which have fast access to attributes (e.g.: the
	/// IMAP model can get the IMAP server to sort it's children).
	//
	class sorter {
		//
		// This is mutable because it is LAZY at getting the values to
		// sort on. It will only get the values to sort by when a sort
		// is required, and a sort is only required when getChildren
		// is called (which is const).
		//
		mutable class sorterImpl* _impl;
	  public:
		//
		/// Create a new sorter object. This object starts off without any children
		/// by default.
		//
		sorter();
		//
		/// Destroy this sorter. All of the information it cached is released.
		//
		virtual ~sorter();
		//
		// void addChild( const std::string& url )
		//
		/// Add the given child URL to the list of children.
		///
		/// \param	url	the URL of the child to add.
		//
		void addChild( const std::string& url );
		//
		// void removeChild( const std::string& url )
		//
		/// Remove the given child from the list children.
		///
		/// \param	url	the URL of the child to remove.
		//
		void removeChild( const std::string& url );
		//
		// bool setSort( const std::string& attr )
		//
		/// Set the name of attribute to sort by. If the given attribute
		/// is not sortable then false is returned and the previous
		/// attribute is used.
		///
		/// By default the list of children is sorted by name.
		///
		/// \param	attr	the name of the attribute to sort by.
		/// \return	true if this attribute will be used to sort, false
		///		otherwise.
		//
		bool setSort( const std::string& attr );
		//
		// const std::string& getSort() const
		// 
		/// Return the name of the attribute which is currently used to
		/// sort by.
		///
		/// \return	the name of the attribute to sort by.
		//
		const std::string& getSort() const;
		//
		// urlCollection getChildren() const
		//
		/// Return a sorted list of children. This method may actually
		/// perform sorting (as this class attempts to avoid creating
		/// models when possible).
		///
		/// \return	a sorted list of child URLs.
		//
		adobe::array_t getChildren() const;
		//
		// void childNotify( const std::string& url, const std::string& attr )
		// 
		/// This method should be called when a child reports that the value
		/// of one of it's attributes has changed. If the url is unknown then
		/// the message is ignored.
		///
		/// \param	url	the URL of the child model which has changed.
		/// \param	attr	the name of the attribute which has changed.
		//
		void childNotify( const std::string& url, const std::string& attr );
	};
};

#endif
